const crypto = require('crypto');
const { promisify } = require('util');
const jwt = require('jsonwebtoken');
const { User, Caregiver } = require('../models');
const { AppError } = require('../middleware/errorHandler');
const logger = require('../utils/logger');
const { validationResult } = require('express-validator');
const { Op } = require('sequelize');

// 生成JWT令牌
const signToken = (id) => {
  return jwt.sign({ id }, process.env.JWT_SECRET, {
    expiresIn: process.env.JWT_EXPIRE || '7d'
  });
};

// 生成刷新令牌
const signRefreshToken = (id) => {
  return jwt.sign({ id }, process.env.JWT_REFRESH_SECRET, {
    expiresIn: process.env.JWT_REFRESH_EXPIRE || '30d'
  });
};

// 创建并发送令牌
const createSendToken = (user, statusCode, res, message = '操作成功') => {
  const token = signToken(user.id);
  const refreshToken = signRefreshToken(user.id);
  
  const cookieOptions = {
    expires: new Date(
      Date.now() + 7 * 24 * 60 * 60 * 1000 // 7天
    ),
    httpOnly: true,
    secure: process.env.NODE_ENV === 'production',
    sameSite: 'strict'
  };
  
  res.cookie('jwt', token, cookieOptions);
  res.cookie('refreshToken', refreshToken, {
    ...cookieOptions,
    expires: new Date(
      Date.now() + 30 * 24 * 60 * 60 * 1000 // 30天
    )
  });
  
  // 移除密码字段
  user.password = undefined;
  
  res.status(statusCode).json({
    status: 'success',
    message,
    token,
    refreshToken,
    data: {
      user
    }
  });
};

// 用户注册
exports.signup = async (req, res, next) => {
  try {
    // 检查验证错误
    const errors = validationResult(req);
    if (!errors.isEmpty()) {
      return next(new AppError('输入数据验证失败', 400));
    }
    
    const {
      username,
      email,
      phone,
      password,
      firstName,
      lastName,
      dateOfBirth,
      gender,
      address
    } = req.body;
    
    // 检查用户是否已存在
    const existingUser = await User.findOne({
      where: {
        [Op.or]: [{ email }, { phone }, { username }]
      }
    });
    
    if (existingUser) {
      let message = '用户已存在';
      if (existingUser.email === email) message = '邮箱已被注册';
      else if (existingUser.phone === phone) message = '手机号已被注册';
      else if (existingUser.username === username) message = '用户名已被使用';
      
      return next(new AppError(message, 400));
    }
    
    // 获取角色类型（主人或喂养师）
    const role = req.body.role || 'user';
    
    // 创建新用户
    const newUser = await User.create({
      username,
      email,
      phone,
      password,
      firstName,
      lastName,
      dateOfBirth,
      gender,
      address,
      role: role // 支持注册为主人(user)或喂养师(caregiver)
    });
    
    // 生成邮箱验证令牌
    const verifyToken = newUser.createEmailVerificationToken();
    await newUser.save({ validate: false });
    
    // 如果注册为喂养师，创建喂养师资料（可后续完善）
    if (role === 'caregiver') {
      await Caregiver.create({
        userId: newUser.id,
        experience: req.body.experience || { years: 0, description: '' },
        emergencyContact: req.body.emergencyContact || {},
        status: 'pending' // 待完善资料
      });
    }
    
    logger.info(`新用户注册: ${newUser.email}, 角色: ${role}`);
    
    // TODO: 发送验证邮件
    // await sendVerificationEmail(newUser.email, verifyToken);
    
    const message = role === 'caregiver' 
      ? '注册成功！您可以完善喂养师资料以提升接单率' 
      : '注册成功，欢迎使用宠物上门喂养服务';
    
    createSendToken(newUser, 201, res, message);
  } catch (error) {
    logger.error('用户注册错误:', error);
    return next(new AppError('注册失败，请稍后重试', 500));
  }
};

// 用户登录
exports.login = async (req, res, next) => {
  try {
    const errors = validationResult(req);
    if (!errors.isEmpty()) {
      return next(new AppError('输入数据验证失败', 400));
    }
    
    const { identifier, password } = req.body; // identifier 可以是邮箱、手机号或用户名
    
    // 1) 检查邮箱和密码是否存在
    if (!identifier || !password) {
      return next(new AppError('请提供登录凭据和密码', 400));
    }
    
    // 2) 检查用户是否存在且密码正确
    const user = await User.scope('withPassword').findOne({
      where: {
        [Op.or]: [
          { email: identifier },
          { phone: identifier },
          { username: identifier }
        ]
      }
    });
    
    if (!user || !(await user.correctPassword(password))) {
      return next(new AppError('登录凭据或密码错误', 401));
    }
    
    // 3) 检查用户是否被禁用
    if (!user.active) {
      return next(new AppError('您的账户已被禁用，请联系管理员', 401));
    }
    
    // 4) 更新最后活动时间
    await user.updateLastActive();
    
    logger.info(`用户登录: ${user.email}`);
    
    // 5) 如果一切正常，发送令牌给客户端
    createSendToken(user, 200, res, '登录成功');
  } catch (error) {
    logger.error('用户登录错误:', error);
    return next(new AppError('登录失败，请稍后重试', 500));
  }
};

// 用户登出
exports.logout = (req, res) => {
  res.cookie('jwt', 'loggedout', {
    expires: new Date(Date.now() + 10 * 1000),
    httpOnly: true
  });
  res.cookie('refreshToken', 'loggedout', {
    expires: new Date(Date.now() + 10 * 1000),
    httpOnly: true
  });
  
  res.status(200).json({ 
    status: 'success',
    message: '登出成功'
  });
};

// 刷新令牌
exports.refreshToken = async (req, res, next) => {
  try {
    // 1) 获取刷新令牌
    let refreshToken;
    if (req.cookies.refreshToken) {
      refreshToken = req.cookies.refreshToken;
    } else if (req.headers.authorization && req.headers.authorization.startsWith('Bearer')) {
      refreshToken = req.headers.authorization.split(' ')[1];
    }
    
    if (!refreshToken) {
      return next(new AppError('未找到刷新令牌', 401));
    }
    
    // 2) 验证刷新令牌
    const decoded = await promisify(jwt.verify)(refreshToken, process.env.JWT_REFRESH_SECRET);
    
    // 3) 检查用户是否仍然存在
    const currentUser = await User.findByPk(decoded.id);
    if (!currentUser) {
      return next(new AppError('该令牌的用户不再存在', 401));
    }
    
    // 4) 检查用户是否被禁用
    if (!currentUser.active) {
      return next(new AppError('您的账户已被禁用', 401));
    }
    
    // 5) 生成新的访问令牌
    const newToken = signToken(currentUser.id);
    
    res.status(200).json({
      status: 'success',
      message: '令牌刷新成功',
      token: newToken
    });
  } catch (error) {
    logger.error('令牌刷新错误:', error);
    return next(new AppError('令牌刷新失败', 401));
  }
};

// 忘记密码
exports.forgotPassword = async (req, res, next) => {
  try {
    const { email } = req.body;
    
    if (!email) {
      return next(new AppError('请提供邮箱地址', 400));
    }
    
    // 1) 根据邮箱获取用户
    const user = await User.findOne({ where: { email } });
    if (!user) {
      return next(new AppError('没有找到该邮箱对应的用户', 404));
    }
    
    // 2) 生成随机重置令牌
    const resetToken = user.createPasswordResetToken();
    await user.save({ validate: false });
    
    // 3) 发送到用户邮箱
    try {
      const resetURL = `${req.protocol}://${req.get('host')}/api/auth/reset-password/${resetToken}`;
      
      // TODO: 发送重置密码邮件
      // await sendPasswordResetEmail(user.email, resetURL);
      
      logger.info(`密码重置邮件已发送: ${user.email}`);
      
      res.status(200).json({
        status: 'success',
        message: '密码重置链接已发送到您的邮箱'
      });
    } catch (err) {
      user.passwordResetToken = undefined;
      user.passwordResetExpires = undefined;
      await user.save({ validate: false });
      
      logger.error('发送重置邮件失败:', err);
      return next(new AppError('发送邮件时出现错误，请稍后重试', 500));
    }
  } catch (error) {
    logger.error('忘记密码错误:', error);
    return next(new AppError('处理请求失败，请稍后重试', 500));
  }
};

// 重置密码
exports.resetPassword = async (req, res, next) => {
  try {
    // 1) 根据令牌获取用户
    const hashedToken = crypto
      .createHash('sha256')
      .update(req.params.token)
      .digest('hex');
    
    const user = await User.findOne({
      where: {
        passwordResetToken: hashedToken,
        passwordResetExpires: { [Op.gt]: new Date() }
      }
    });
    
    // 2) 如果令牌未过期，且有用户，设置新密码
    if (!user) {
      return next(new AppError('令牌无效或已过期', 400));
    }
    
    const { password, passwordConfirm } = req.body;
    
    if (!password || !passwordConfirm) {
      return next(new AppError('请提供新密码和确认密码', 400));
    }
    
    if (password !== passwordConfirm) {
      return next(new AppError('密码和确认密码不匹配', 400));
    }
    
    user.password = password;
    user.passwordResetToken = undefined;
    user.passwordResetExpires = undefined;
    await user.save();
    
    logger.info(`用户重置密码: ${user.email}`);
    
    // 3) 更新 changedPasswordAt 属性（在 pre save 中间件中处理）
    
    // 4) 登录用户，发送 JWT
    createSendToken(user, 200, res, '密码重置成功');
  } catch (error) {
    logger.error('重置密码错误:', error);
    return next(new AppError('重置密码失败，请稍后重试', 500));
  }
};

// 更新密码
exports.updatePassword = async (req, res, next) => {
  try {
    const { currentPassword, newPassword, newPasswordConfirm } = req.body;
    
    if (!currentPassword || !newPassword || !newPasswordConfirm) {
      return next(new AppError('请提供当前密码、新密码和确认密码', 400));
    }
    
    if (newPassword !== newPasswordConfirm) {
      return next(new AppError('新密码和确认密码不匹配', 400));
    }
    
    // 1) 获取用户
    const user = await User.scope('withPassword').findByPk(req.user.id);
    
    // 2) 检查当前密码是否正确
    if (!(await user.correctPassword(currentPassword))) {
      return next(new AppError('当前密码错误', 401));
    }
    
    // 3) 如果正确，更新密码
    user.password = newPassword;
    await user.save();
    
    logger.info(`用户更新密码: ${user.email}`);
    
    // 4) 登录用户，发送 JWT
    createSendToken(user, 200, res, '密码更新成功');
  } catch (error) {
    logger.error('更新密码错误:', error);
    return next(new AppError('更新密码失败，请稍后重试', 500));
  }
};

// 验证邮箱
exports.verifyEmail = async (req, res, next) => {
  try {
    // 1) 根据令牌获取用户
    const hashedToken = crypto
      .createHash('sha256')
      .update(req.params.token)
      .digest('hex');
    
    const user = await User.findOne({
      where: {
        emailVerificationToken: hashedToken,
        emailVerificationExpires: { [Op.gt]: new Date() }
      }
    });
    
    // 2) 如果令牌未过期，且有用户，验证邮箱
    if (!user) {
      return next(new AppError('验证令牌无效或已过期', 400));
    }
    
    user.emailVerified = true;
    user.emailVerificationToken = undefined;
    user.emailVerificationExpires = undefined;
    await user.save({ validate: false });
    
    logger.info(`用户邮箱验证成功: ${user.email}`);
    
    res.status(200).json({
      status: 'success',
      message: '邮箱验证成功'
    });
  } catch (error) {
    logger.error('邮箱验证错误:', error);
    return next(new AppError('邮箱验证失败，请稍后重试', 500));
  }
};

// 重新发送验证邮件
exports.resendVerificationEmail = async (req, res, next) => {
  try {
    const user = await User.findByPk(req.user.id);
    
    if (user.emailVerified) {
      return next(new AppError('邮箱已经验证过了', 400));
    }
    
    // 生成新的验证令牌
    const verifyToken = user.createEmailVerificationToken();
    await user.save({ validate: false });
    
    // TODO: 发送验证邮件
    // await sendVerificationEmail(user.email, verifyToken);
    
    logger.info(`重新发送验证邮件: ${user.email}`);
    
    res.status(200).json({
      status: 'success',
      message: '验证邮件已重新发送'
    });
  } catch (error) {
    logger.error('重新发送验证邮件错误:', error);
    return next(new AppError('发送验证邮件失败，请稍后重试', 500));
  }
};

// 获取当前用户信息
exports.getMe = async (req, res, next) => {
  try {
    const user = await User.findByPk(req.user.id);
    
    res.status(200).json({
      status: 'success',
      data: {
        user
      }
    });
  } catch (error) {
    logger.error('获取用户信息错误:', error);
    return next(new AppError('获取用户信息失败', 500));
  }
};

// 检查认证状态
exports.checkAuth = async (req, res, next) => {
  try {
    if (req.user) {
      res.status(200).json({
        status: 'success',
        authenticated: true,
        data: {
          user: req.user
        }
      });
    } else {
      res.status(401).json({
        status: 'fail',
        authenticated: false,
        message: '未认证'
      });
    }
  } catch (error) {
    logger.error('检查认证状态错误:', error);
    return next(new AppError('检查认证状态失败', 500));
  }
};

// 微信小程序手机号登录/注册
exports.wechatPhoneLogin = async (req, res, next) => {
  try {
    const { code, encryptedData, iv, phone } = req.body;
    
    // 检查必要参数
    if (!phone) {
      return next(new AppError('请提供手机号', 400));
    }
    
    // TODO: 验证微信手机号的真实性
    // 这里需要调用微信 API 解密 encryptedData
    // const phoneNumber = await decryptWechatData(encryptedData, iv, sessionKey);
    
    // 查找或创建用户
    let user = await User.findOne({ where: { phone } });
    
    if (!user) {
      // 用户不存在，自动注册
      const username = `wx_${phone.slice(-8)}_${Date.now().toString(36)}`;
      const randomPassword = crypto.randomBytes(16).toString('hex');
      
      user = await User.create({
        username,
        phone,
        email: `${username}@wechat.temp`, // 临时邮箱，后续可完善
        password: randomPassword,
        firstName: '微信',
        lastName: '用户',
        role: 'user',
        emailVerified: false, // 微信用户默认邮箱未验证
        phoneVerified: true, // 微信手机号已验证
        wechatOpenId: req.body.openid || null, // 如果有 openid
        wechatUnionId: req.body.unionid || null // 如果有 unionid
      });
      
      logger.info(`微信用户自动注册: ${phone}`);
    } else {
      // 用户已存在，更新微信信息
      if (req.body.openid) {
        await user.update({ 
          wechatOpenId: req.body.openid,
          wechatUnionId: req.body.unionid || user.wechatUnionId,
          phoneVerified: true
        });
      }
      logger.info(`微信用户登录: ${phone}`);
    }
    
    // 检查用户是否被禁用
    if (!user.active) {
      return next(new AppError('您的账户已被禁用，请联系管理员', 401));
    }
    
    // 更新最后活动时间
    await user.updateLastActive();
    
    // 发送令牌
    createSendToken(user, 200, res, '登录成功');
  } catch (error) {
    logger.error('微信手机号登录错误:', error);
    return next(new AppError('登录失败，请稍后重试', 500));
  }
};